#include "UserInfoService.h"
#include "UserInfo.pb.h"
#include "CryptoUtil.h"

#include <signal.h>
#include <nlohmann/json.hpp>
#include <workflow/WFFacilities.h>
#include <workflow/MySQLResult.h>
#include <workflow/WFTaskFactory.h>
#include <string>
#include <vector>

using namespace srpc;
using namespace protocol;
using std::string;
using std::vector;


namespace
{

	using json = nlohmann::json;

	WFFacilities::WaitGroup wait_group(1);

	//默认的注册服务器的端口
	constexpr const unsigned short DEFAULT_INFO_PORT = 1236;
	//默认的注册服务器的ip
	constexpr const char* DEFAULT_INFO_IP = "127.0.0.1";
	//mysql的url
	constexpr const char* MYSQL_URL = "mysql://root:123@127.0.0.1/CloudDisk2";
	//最大重试次数
	constexpr const int RE_TRY_MAX = 3;

	void sig_handler(int signo)
	{
		wait_group.done();
	}


	/* ************************************************************************************ */
	/* *******************************获取用户信息****************************************** */
	/* ************************************************************************************ */

	void handleUserInfo(::l::UserInfoResponse* response, string username, WFMySQLTask* task) {

		// 任务失败: 及早失败原则
		if (task->get_state() != WFT_STATE_SUCCESS) {
			response->set_statuscode(500);
#ifdef BUG
			std::cerr << "Error: " << WFGlobal::get_error_string(task->get_state(), task->get_error());
#endif
			return;
		}

		MySQLResponse* resp = task->get_resp();
		MySQLResultCursor cursor{ resp };

		if (cursor.get_cursor_status() != MYSQL_STATUS_GET_RESULT || cursor.get_rows_count() == 0) {

			response->set_statuscode(400);
#ifdef BUG
			std::cout << "mysql failed This user does not exist\n" << "\n";
#endif
			return;
		}

		vector<MySQLCell> record{};
		cursor.fetch_row(record);
		string create_at{ record[0].as_datetime() };

		json userinfo{};
		userinfo["data"] = { {"Username", username}, {"SignupAt",create_at} };
		response->set_statuscode(200);
		response->set_userinfo(userinfo.dump());

#ifdef BUG
		std::cout << "json:\n " << userinfo.dump(2) << "\n";
#endif

	}


}//end of anonymous namaspace



class UserInfoServiceImpl : public ::l::UserInfo::Service
{
public:

	void UserInfo(::l::UserInfoRequest* request, ::l::UserInfoResponse* response, srpc::RPCContext* ctx) override
	{
		//获取username和password
		string username{ request->username() };

		string url{ MYSQL_URL };
		string sql{ "SELECT  created_at FROM users WHERE username = \"" };
		sql.append(username).append("\" AND tomb = 0");
#ifdef BUG
		std::cout << "info sql: " << sql << "\n";
#endif

		WFMySQLTask* task = WFTaskFactory::create_mysql_task(MYSQL_URL, RE_TRY_MAX, std::bind(handleUserInfo, response, std::move(username), std::placeholders::_1));

		task->get_req()->set_query(sql);

		SeriesWork* series = ctx->get_series();
		series->push_back(task);

	}
};

int main()
{
	signal(SIGINT, sig_handler);

	SRPCServer server;

	UserInfoServiceImpl userinfo_impl;
	server.add_service(&userinfo_impl);

	if (server.start(DEFAULT_INFO_PORT) == 0) {
		wait_group.wait();
		server.stop();
	}
	else {
#ifdef BUG
		std::cout << "userinfo server start failed\n";
#endif
	}

	google::protobuf::ShutdownProtobufLibrary();
	return 0;
}
